//proto文件生成器，主要生成Unity内调用API

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Google.Protobuf;
using UnityEngine;

public class ProtoCodeGenerator
{
    ProtoContent content;
    StringBuilder sb = new StringBuilder();
    public void SetProtoStruct(ProtoContent content)
    {
        this.content = content;
    }

    public string WriteFileCode(string old_code = "")
    {
        string code = "";
        code += GetHeadCode(old_code);
        code += GetRegisterProtocolCode();
        code += GetRequestCode();
        code += GetResponseCode(old_code);

        code += GetEndCode();

        return code;
    }

    string GetHeadCode(string old_code = "")
    {
        sb.AppendLine("//开始写入，命名空间不会覆盖");
        var old_namespace_using = RegexMgr.Instance.RegexBeginAndEnd(old_code,"//开始写入，命名空间不会覆盖","//结束写入，命名空间不会覆盖");
        if(old_namespace_using != "")
        {
            sb.AppendLine(old_namespace_using.Trim());
        }else 
        {
            sb.AppendLine("using UnityEngine;");
            sb.AppendLine("using System.Collections;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using Google.Protobuf;");
        }

        sb.AppendLine("//结束写入，命名空间不会覆盖");
        sb.AppendLine($"namespace {content.NameSpace}");
        sb.AppendLine("{");
        sb.AppendLine($"\tpublic class {content.NameSpace}Net : Singleton<{content.NameSpace}Net>");
        sb.AppendLine("\t{");
        sb.AppendLine("\t\tpublic override void Init()");
        sb.AppendLine("\t\t{");
        sb.AppendLine("\t\t\tbase.Init();");
        sb.AppendLine("\t\t\tRegisterProtocol();");
        sb.AppendLine("\t\t}");
        sb.AppendLine();
        sb.AppendLine("\t\tpublic void RegisterProtocol()");
        sb.AppendLine("\t\t{");

        var code = sb.ToString();
        sb.Clear();
        return code;
    }

    string GetEndCode()
    {
        sb.AppendLine("\t}");
        sb.AppendLine("}");

        var code = sb.ToString();
        sb.Clear();
        return code;
    }

    string GetRegisterProtocolCode()
    {
        sb.AppendLine("\t\t\t//开始自动生成注册protocol");
        foreach (var item in content.ResMsg)
        {
            sb.AppendLine($"\t\t\tNetMgr.Instance.RegisterProtocol<{item.Msg_name}>({item.Protocol_id},{item.Msg_name}_Res);");
        }
        sb.AppendLine("\t\t\t//结束自动生成注册protocol");
        sb.AppendLine("\t\t}");
        sb.AppendLine();

        var code = sb.ToString();
        sb.Clear();
        return code;
    }

    string GetRequestCode()
    {
        foreach (var msg in content.ReqMsg)
        {
            sb.AppendLine($"\t\t//开始自动生成{msg.Msg_name}请求");
            sb.AppendLine($"\t\t/// <summary>");
            if(msg.Desc != "")
                sb.AppendLine($"\t\t/// {msg.Desc}");
            else 
                sb.AppendLine($"\t\t/// {msg.Msg_name}请求");

            sb.AppendLine($"\t\t/// </summary>");
            foreach (var classInfo in msg.infos)
            {
                sb.AppendLine($"\t\t/// <param name=\"{classInfo.ClassName.ToLower()}\">{classInfo.Desc}</param>");
            }

            var fun_name = $"\t\tasync public void {msg.Msg_name}_Req(";
            var params_str = "";
            foreach (var item in msg.infos)
            {
                if(item.Is_array == false)
                    params_str += item.ClassType + " " + item.ClassName.ToLower() + ",";
                else 
                    params_str += item.ClassType + "[] " + item.ClassName.ToLower() + ",";
            }
            if(params_str.Length > 0)
                params_str = params_str.Substring(0,params_str.Length -1);
            params_str += ")";
            fun_name += params_str;
            sb.AppendLine(fun_name);
            sb.AppendLine("\t\t{");
            sb.AppendLine($"\t\t\t{msg.Msg_name} req = new {msg.Msg_name}();");
            foreach (var item in msg.infos)
            {
                if(item.Is_array == false)
                    sb.AppendLine($"\t\t\treq.{item.ClassName} = {item.ClassName.ToLower()};");
                else 
                {
                    sb.AppendLine($"\t\t\tfor(int i = 0;i < {item.ClassName.ToLower()}.Length ; i++)");
                    sb.AppendLine("\t\t\t{");
                    sb.AppendLine($"\t\t\t\tvar item = {item.ClassName.ToLower()}[i];");
                    sb.AppendLine($"\t\t\t\treq.{item.ClassName}.Add(item);");


                    sb.AppendLine("\t\t\t\t}");

                }
            }
            sb.AppendLine("\t\t\t//send protocol");

            sb.AppendLine($"\t\t\tawait NetMgr.Instance.SendProtocol({msg.Protocol_id},req);");
            sb.AppendLine("\t\t}");
            sb.AppendLine($"\t\t//结束自动生成{msg.Msg_name}请求");
        }
        sb.AppendLine();

        var code = sb.ToString();
        sb.Clear();
        return code;
    }

    string GetResponseCode(string old_code = "")
    {
        sb.AppendLine($"\t\t//以下是自动生成的响应，不会覆盖手写的代码");
        foreach (var msg in content.ResMsg)
        {
            var begin = $"//开始自动生成{msg.Msg_name}响应";
            var end = $"//结束自动生成{msg.Msg_name}响应";

            var filter_begin = $"\t\tpublic void {msg.Msg_name}_Res";
            var old_response = RegexMgr.Instance.RegexBeginAndEnd(old_code,filter_begin,end);
            if(old_response != "")
            {
                sb.AppendLine($"\t\t{begin}");
                var new_str = "";

                new_str += ($"\t\t/// <summary>\n");
                if(msg.Desc != "")
                {
                    new_str += ($"\t\t/// {msg.Desc}\n");
                }
                else 
                    new_str += ($"\n\t\t/// {msg.Msg_name}响应\n");

                new_str += ($"\t\t/// </summary>\n");

                new_str += ("\t\t/// <param name=\"res\">\n");
                new_str += ($"\t\t/// {msg.Desc}\n");
                new_str += ($"\t\t/// </param>\n");
                new_str += ($"\t\t/// <value>\n");
                foreach (var classInfo in msg.infos)
                {
                    new_str += ($"\t\t/// res.{classInfo.ClassName}\t{classInfo.Desc}\n");
                }
                new_str += ($"\t\t/// </value>\n");
                var new_code = new_str + filter_begin + old_response.TrimStart();
                sb.AppendLine(new_code.TrimEnd());
                sb.AppendLine($"\t\t{end}");
                sb.AppendLine();
                continue;
            }
            sb.AppendLine($"\t\t{begin}");
            sb.AppendLine($"\t\t/// <summary>");

            if(msg.Desc != "")
                sb.AppendLine($"\t\t/// {msg.Desc}");
            else 
                sb.AppendLine($"\t\t/// {msg.Msg_name}响应");

            sb.AppendLine($"\t\t/// </summary>");
            sb.AppendLine($"\t\t/// <param name=\"res\">");
            sb.AppendLine($"\t\t/// {msg.Desc}");
            sb.AppendLine($"\t\t/// </param>");
            sb.AppendLine($"\t\t/// <value>");
            foreach (var classInfo in msg.infos)
            {
                sb.AppendLine($"\t\t/// res.{classInfo.ClassName}\t{classInfo.Desc}");
            }
            sb.AppendLine($"\t\t/// </value>");

            sb.AppendLine($"\t\tpublic void {msg.Msg_name}_Res({msg.Msg_name} res, int code)");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\tif(code == 0)");
            sb.AppendLine("\t\t\t{");
            sb.AppendLine("\t\t\t\t//TODO");
            sb.AppendLine("\t\t\t\t");
            sb.AppendLine("\t\t\t}");
            sb.AppendLine("\t\t}");
            sb.AppendLine($"\t\t{end}");
            sb.AppendLine();
        }

        var code = sb.ToString();
        sb.Clear();
        return code;
    }

    public void Clear()
    {
        sb.Clear();
        content = null;
    }
    
}